﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Platform.Infrastructure;
using Platform.ObjectModel.Collections;
using Platform.ObjectModel.Serializers;

namespace Platform.ObjectModel.Design
{

	/// <summary>
	/// Representa o campo de um documento
	/// </summary>
	public class FieldDescriptor : DocumentFlake //: DataObjectFlake, IQualifiedDataObject
	{
		/// <summary>
		/// 
		/// </summary>
		internal static readonly DataObjectName FieldSchemaNamespace = new DataObjectName( "Field", "Plaform.ObjectModel" );

		//private DataObjectName formatName;


		public FieldDescriptor( DataObjectName name )
			: this( name, ( string )null )
		{ }

		public FieldDescriptor( DataObjectName name, string friendlyName )
			: base( FieldSchemaNamespace )
		{
			Arguments.IsNotNull( "name", name );

			this.FormatterName = null;
			this.QualifiedName = name;
			this.FriendlyName = ( String.IsNullOrEmpty( friendlyName ) ? name.FullName : friendlyName );
			this.Rules = new FieldRulesCollection();
		}

		
		/// <summary>
		/// Obtém ou define o nome que será exibido para o usuário do sistema
		/// </summary>
		public string FriendlyName
		{ get; set; }

		/// <summary>
		/// Obtém ou define uma pequena ajuda para exibir durante o preenchimento dos dados do campo
		/// </summary>
		public string TooltipText
		{ get; set; }

		/// <summary>
		/// Indica se o campo é indexado para a pesquisa FullText
		/// </summary>
		public bool Searchable
		{ get; set; }

		/// <summary>
		/// Obtém ou define o tipo de dados que é armazenado nesse campo
		/// </summary>
		public FieldType Type
		{ get; set; }

		/// <summary>
		/// Obtém ou define o formato que o valor do campo deve ser serializado.
		/// </summary>
		/// <remarks>
		/// <para>Se nenhum for definido, o componente que implementa o Storage irá definir qual será utilizado.</para>
		/// <para>Para os tipos primitivos sempre são serializados como um vetor de <see cref="System.Byte"/>.</para>
		/// </remarks>
		public DataObjectName FormatterName
		{ get; set; }

		#region IQualifiedDataObject Members

		/// <summary>
		/// Obtém o nome que identifica o campo
		/// </summary>
		public DataObjectName QualifiedName
		{
			get;
			private set;
		}

		#endregion

		/// <summary>
		/// Obtém ou define as regras para alterar os dados do campo
		/// </summary>
		/// <remarks>
		/// Cada nova <see cref="RuleBase"/> deve ser registrado assim como é registrado um schema
		/// </remarks>
		public FieldRulesCollection Rules
		{
			get;
			private set;
		}

		

		/// <summary>
		/// Realiza a criação do schema que define um campo de um documento
		/// </summary>
		/// <returns></returns>
		internal static Schema CreateFieldSchema()
		{
			SchemaBuilder<FieldDescriptor> builder = new SchemaBuilder<FieldDescriptor>( new Schema( FieldSchemaNamespace ) );

			builder.Field( f => f.FriendlyName ).FriendlyName( "Nome" );
			builder.Field( f => f.Searchable ).FriendlyName( "Pesquisável" );
			builder.Field( f => f.TooltipText ).FriendlyName( "Dica de como preencher" );
			builder.Field( f => f.Type ).FriendlyName( "Tipo do conteúdo do campo" );

			return builder.Schema;
		}

		#region [ class FieldRulesCollection ]

		/// <summary>
		/// 
		/// </summary>
		public sealed class FieldRulesCollection : CollectionBase<RuleBase>
		{

			public FieldRulesCollection()
				: base()
			{ }
		}

		#endregion
	}

}
